
/*
 * Copyright (c) 2021. Dylan Cai
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

@file:Suppress("unused")

//package com.dylanc.longan
package com.gitee.wsl.ext.string

import com.gitee.wsl.net.url.decodeURLPart
import com.gitee.wsl.net.url.encodeURLPath

/*import okio.ByteString.Companion.decodeBase64
import okio.ByteString.Companion.encode
import okio.ByteString.Companion.toByteString*/

/*fun ByteArray.toHexString():String =  toByteString().hex()

fun ByteArray.base64Encode():ByteArray = toByteString().base64().toByteArray()

fun ByteArray.base64EncodeToString(): String = toByteString().base64()

fun String.base64Decode(): ByteArray? = decodeBase64()?.toByteArray()*/

// sealed interface Encoding {
//    val alphabet: String
//    val requiresPadding: Boolean
//
//    data object Standard : Encoding {
//        override val alphabet: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
//        override val requiresPadding: Boolean = true
//    }
//
//    data object UrlSafe : Encoding {
//        override val alphabet: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
//        override val requiresPadding: Boolean = false // Padding is optional
//    }
//}

//private fun String.encodeInternal(encoding: Encoding): String {
//    val padLength = when (length % 3) {
//        1 -> 2
//        2 -> 1
//        else -> 0
//    }
//    val raw = this + 0.toChar().toString().repeat(maxOf(0, padLength))
//    val encoded = raw.chunkedSequence(3) {
//        Triple(it[0].code, it[1].code, it[2].code)
//    }.map { (first, second, third) ->
//        (0xFF.and(first) shl 16) + (0xFF.and(second) shl 8) + 0xFF.and(third)
//    }.map { n ->
//        sequenceOf((n shr 18) and 0x3F, (n shr 12) and 0x3F, (n shr 6) and 0x3F, n and 0x3F)
//    }.flatten()
//        .map { encoding.alphabet[it] }
//        .joinToString("")
//        .dropLast(padLength)
//    return when (encoding.requiresPadding) {
//        true -> encoded.padEnd(encoded.length + padLength, '=')
//        else -> encoded
//    }
//}
//
//private fun String.decodeInternal(encoding: Encoding): Sequence<Int> {
//    val padLength = when (length % 4) {
//        1 -> 3
//        2 -> 2
//        3 -> 1
//        else -> 0
//    }
//    return padEnd(length + padLength, '=')
//        .replace("=", "A")
//        .chunkedSequence(4) {
//            (encoding.alphabet.indexOf(it[0]) shl 18) + (encoding.alphabet.indexOf(it[1]) shl 12) +
//                    (encoding.alphabet.indexOf(it[2]) shl 6) + encoding.alphabet.indexOf(it[3])
//        }
//        .map { sequenceOf(0xFF.and(it shr 16), 0xFF.and(it shr 8), 0xFF.and(it)) }
//        .flatten()
//}

// fun ByteArray.toCharArray(): CharArray {
//    val chars = CharArray(size)
//    for (i in chars.indices) {
//        chars[i] = get(i).toInt().toChar()
//    }
//    return chars
//}

/* val String.toHexString:String
   get() = encode().hex()*/

 //val String.base64EncodedString: String
    //get() = encodeInternal(Encoding.Standard)

// val String.base64DecodedString: String
//     get() = decodeInternal(Encoding.Standard).map { it.toChar() }.joinToString("").dropLast(count { it == '=' })


/**
 * Decodes symbols using base64.
 */
//fun String.decodeBase64ToString(): String = this.encodeToByteArray().decodeBase64ToString()

/**
 * Encodes symbols using base64.
 */
//fun String.encodeBase64ToString(): String = this.encodeToByteArray().encodeBase64ToString()

/**
 * Decodes symbols using base64.
 */
//fun String.decodeBase64(): ByteArray = this.encodeToByteArray().decodeBase64()


// val String.base64UrlEncodedString: String
//    get() = encodeInternal(Encoding.UrlSafe)
//
// val String.base64UrlDecodedString: String
//    get() {
//        val ret = decodeInternal(Encoding.UrlSafe).map { it.toChar() }
//        val foo = ret.joinToString("")
//        val bar = foo.dropLast(count { it == '=' })
//        return bar.filterNot { it.code == 0 }
//    }

/**
 * Return the binary encoded string padded with one space
 *
 * @param input The input.
 * @return binary string
 */
fun String.encodeBinaryToString(): String {
    if (isEmpty()) return ""
    val sb = StringBuilder()
    for (i in toCharArray()) {
        sb.append(i.code.toByte()).append(" ")
    }
    return sb.deleteAt(sb.length - 1).toString()
}

/**
 * Return UTF-8 String from binary
 *
 * @param input binary string
 * @return UTF-8 String
 */
fun String.decodeBinaryToString(): String {
    if (isEmpty()) return ""
    val splits = split(" ").toTypedArray()
    val sb = StringBuilder()
    for (split in splits) {
        sb.append(split.toInt(2).toChar())
    }
    return sb.toString()
}


fun String.urlEncode(): String = this.encodeURLPath()

fun String.urlDecode(): String = this.decodeURLPart()
